﻿using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Common.HttpHelper
{
    public class HttpRequestHelper
    {
        private static RestClient GetClient(string requestUrl)
        {
            return new RestClient(requestUrl);
        }
        /// <summary>
        /// 预请求方法
        /// </summary>
        /// <typeparam name="TResult">返回结果类型</typeparam>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="headerInfo">信息</param>
        /// <param name="doRequest">对请求内容进行操作,并发起请求</param>
        /// <returns>请求的返回结果</returns>
        public static TResult PreRequest<TResult>(string requestUrl, Dictionary<string, string> headerInfo,Func<RestClient, RestRequest, TResult> doRequest)
        {
            RestClient client = GetClient(requestUrl);
            RestRequest request = new ();
            if(headerInfo != null)
            {
                foreach (var key in headerInfo.Keys)
                {
                    request.AddHeader(key, headerInfo[key]);
                }
            }
            
            return doRequest.Invoke(client,request);
        }
        /// <summary>
        /// 使用实体model发起post请求并返回一个实体model
        /// </summary>
        /// <typeparam name="T">发送的数据的类型T</typeparam>
        /// <typeparam name="TResult">返回的类型实体</typeparam>
        /// <param name="RequestUrl">请求的地址</param>
        /// <param name="Data">发送的数据</param>
        /// <param name="HeaderInfo">头数据</param>
        /// <returns></returns>
        public async static Task<TResult?> PostByModelReturnModel<T,TResult>(string requestUrl,T Data, Dictionary<string, string> headerInfo) where T : class
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                request.AddJsonBody(Data);
                return client.PostAsync<TResult>(request);
            });
        }
        /// <summary>
        /// 使用实体model发起post请求并返回结果字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="Data"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        public async static Task<string?> PostByModelReturnString<T>(string requestUrl, T Data, Dictionary<string, string> headerInfo) where T : class
        {
            return (await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                request.AddJsonBody(Data);
                return client.PostAsync(request);
            })).Content;
        }
        /// <summary>
        /// 使用Json字符串发起post请求并返回一个实体对象
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="jsonData"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        public async static Task<TResult?> PostByJsonReturnModel<TResult>(string requestUrl, string jsonData, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                request.AddBody(jsonData);
                return client.PostAsync<TResult>(request);
            });
        }
        /// <summary>
        /// 使用Json字符串发起post请求并返回json字符串
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="RequestUrl"></param>
        /// <param name="JsonData"></param>
        /// <param name="HeaderInfo"></param>
        /// <returns></returns>
        public async static Task<string?> PostByJsonGetByString<TResult>(string RequestUrl, string JsonData, Dictionary<string, string> HeaderInfo)
        {
            return (await PreRequest(RequestUrl, HeaderInfo, (client, request) =>
            {
                request.AddBody(JsonData);
                return client.PostAsync(request);
            })).Content;
        }
        /// <summary>
        /// 使用form的方式发起post请求并返回string字符串
        /// </summary>
        /// <param name="RequestUrl"></param>
        /// <param name="formData"></param>
        /// <param name="HeaderInfo"></param>
        /// <returns></returns>
        public async static Task<string?> PostByFormReturnString(string RequestUrl,Dictionary<string,string> formData, Dictionary<string, string> HeaderInfo)
        {
            return (await PreRequest(RequestUrl, HeaderInfo, (client, request) =>
            {
                foreach(string key in formData.Keys)
                {
                    request.AddParameter(key, formData[key]);
                }
                return client.PostAsync(request);
            })).Content;
        }
        /// <summary>
        /// 使用form的方式发起post请求并返回实体模型
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="formData"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        public async static Task<TResult?> PostByFormReturnModel<TResult>(string requestUrl, Dictionary<string, string> formData, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                foreach (string key in formData.Keys)
                {
                    request.AddParameter(key, formData[key]);
                }
                return client.PostAsync<TResult>(request);
            });
        }
        /// <summary>
        /// 发起get请求并返回一个结果模型
        /// </summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="query">查询参数字典</param>
        /// <param name="headerInfo">头信息</param>
        /// <returns></returns>

        public async static Task<TResult?> GetByDicReturnModel<TResult>(string requestUrl,Dictionary<string,string> query , Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                if(query != null)
                {
                    foreach (string key in query.Keys)
                    {
                        request.AddQueryParameter(key, query[key]);
                    }
                }
                
                return client.GetAsync<TResult>(request);
            });
        }
        /// <summary>
        /// 发起get请求并返回一个字符串
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="query"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        public async static Task<string?> GetByDicReturnString(string requestUrl, Dictionary<string, string> query, Dictionary<string, string> headerInfo)
        {
            return (await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                if (query != null)
                {
                    foreach (string key in query.Keys)
                    {
                        request.AddQueryParameter(key, query[key]);
                    }
                }
                return client.GetAsync(request);
            })).Content;
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="filePath"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        /// <exception cref="FileNotFoundException"></exception>
        public async static Task<TResult?> UploadFile<TResult>(string requestUrl, string filePath, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException();
                }
                request.AddFile("file", filePath);
                return client.PostAsync<TResult>(request);
            });
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="filePath"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        /// <exception cref="FileNotFoundException"></exception>
        public async static Task<string?> UploadFile(string requestUrl, string filePath, Dictionary<string, string> headerInfo)
        {
            return (await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException();
                }
                request.AddFile("file", filePath);
                return client.PostAsync(request);
            })).Content;
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="requestUrl"></param>
        /// <param name="file"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>
        public async static Task<TResult?> UploadFile<TResult>(string requestUrl,byte[] file, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                request.AddFile("file",file,"file");
                return client.PostAsync<TResult>(request);
            });
        }
        public async static Task<string?> UploadFile(string requestUrl, byte[] file, Dictionary<string, string> headerInfo)
        {
            return (await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                request.AddFile("file", file, "file");
                return client.PostAsync(request);
            })).Content;
        }

        public async static Task<TResult?> UploadFiles<TResult>(string requestUrl,Dictionary<string, byte[]> fileDic, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                foreach(string key in fileDic.Keys)
                {
                    request.AddFile(key, fileDic[key], key);
                }
                
                return client.PostAsync<TResult>(request);
            });
        }

        public async static Task<string?> UploadFiles(string requestUrl, Dictionary<string, byte[]> fileDic, Dictionary<string, string> headerInfo)
        {
            return (await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                foreach (string key in fileDic.Keys)
                {
                    request.AddFile(key, fileDic[key], key);
                }
                return client.PostAsync(request);
            })).Content;
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="query"></param>
        /// <param name="headerInfo"></param>
        /// <returns></returns>

        public async static Task<byte[]?> DownloadFileToByte(string requestUrl, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                return client.DownloadDataAsync(request);
            });
        }

        public async static Task<Stream?> DownloadFileToStream(string requestUrl, Dictionary<string, string> headerInfo)
        {
            return await PreRequest(requestUrl, headerInfo, (client, request) =>
            {
                return client.DownloadStreamAsync(request);
            });
        }
    }
}
